package com.cn.JUC.utils.case11;

import lombok.extern.slf4j.Slf4j;

import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * @Title CompletionStage
 * @Description CompletionStage使用：接口如何描述串行关系、AND 聚合关系、OR 聚合关系以及异常处理。
 * 补充：1）CompletableFuture 类还实现了 CompletionStage 接口，这个接口内容实在是太丰富了。
 * 补充：2）举前面烧水泡茶的例子，其中洗水壶和烧开水就是串行关系，
 *         洗水壶、烧开水和洗茶壶、洗茶杯这两组任务之间就是并行关系，
 *         而烧开水、拿茶叶和泡茶就是汇聚关系。
 * @Author CAI ZHAI
 * @Date 2021/9/8 14:48
 **/
@Slf4j
public class CompletionStageImpl{
    public static void main(String[] args){
        //supplyAsync();
    
        //or();
    
        exception();
    }
    
    /**
     * @Title CompletionStage描述串行
     * @Description 示例：首先通过 supplyAsync() 启动一个异步流程，之后是两个串行操作，
     * 整体看起来还是挺简单的。不过，虽然这是一个异步流程，但任务①②③却是串行执行的，②依赖①的执行结果，③依赖②的执行结果。
     **/
    private static void supplyAsync(){
    
        CompletableFuture<String> f0 = CompletableFuture.supplyAsync(
                        () -> "Hello World")      //①
                        .thenApply(s -> s + " QQ")  //②
                        .thenApply(String::toUpperCase);//③
        System.out.println(f0.join());
        //输出结果
        //HELLO WORLD QQ
    }
    
    /**
     * @Title CompletionStage描述AND汇聚
     * @Description 示例：烧水泡茶的thenCombine
     **/
    private static void and(){
        BoilWaterToMakeTea2.boilWaterToMakeTea2();
    }
    
    /**
     * @Title CompletionStage描述OR汇聚
     * @Description 示例：随机返回f1或f2的结果
     **/
    private static void or(){
        CompletableFuture<String> f1 =
                CompletableFuture.supplyAsync(()->{
                    int t = getRandom(5, 10);
                    log.info("f1："+t);
                    sleep(t);
                    return String.valueOf(t);
                });
    
        CompletableFuture<String> f2 =
                CompletableFuture.supplyAsync(()->{
                    int t = getRandom(5, 10);
                    log.info("f2："+t);
                    sleep(t);
                    return String.valueOf(t);
                });
    
        CompletableFuture<String> f3 = f1.applyToEither(f2,s -> s);
    
        System.out.println("输出结果："+f3.join());
    }
    
    /**
     * @Title CompletionStage描述异常
     * @Description 示例：非异步用try catch，异步如何使用？比try catch还简单，支持链式编程。
     **/
    private static void exception(){
    
        CompletableFuture<Integer> f0 = CompletableFuture
                             .supplyAsync(()->(7/0))
                             .thenApply(r->r*10)
                             .exceptionally(e->1); //如果出现异常，返回0
        System.out.println(f0.join());
    }
    
    
    
    private static int getRandom(int i,int i1){
        int i2 = new Random().nextInt(6);
        return i2;
    }
    static void sleep(int t) {
        try {
            TimeUnit.SECONDS.sleep(t);
        }catch(InterruptedException e){}
    }
}
